package db;

import java.util.ArrayList;

/**
 * Controller Class, manages the global lists countries, organizations and
 * places including checks for duplicates and replace strategy.
 * 
 * @author markus
 * 
 */
public class Controller {

	private ArrayList<Country> countries = new ArrayList<Country>();
	private ArrayList<Organization> organizations = new ArrayList<Organization>();
	private ArrayList<Place> places = new ArrayList<Place>();
	private static boolean debug = false;

	/**
	 * Add the country to the global country list and check, if there is a
	 * capital with no associated country.
	 * 
	 * @param countryToAdd
	 */
	public void addCountry(Country countryToAdd) {
		countries.add(countryToAdd);

		// check if added country has a capital + add country to this place
		if (countryToAdd.getCapital() != null) {
			for (Place p : places) {
				if (p.getName().equals(countryToAdd.getCapital().getName())) {
					p.setCountry(countries.get(countries.size() - 1));
				}
			}
		}
	}

	public ArrayList<Country> getCountries() {
		return countries;
	}

	/**
	 * Add a single organization to the Array
	 * 
	 * @param organization
	 *            name
	 * @return true if successfully added
	 */
	public void addOrganization(String name) {
		for (Organization org : organizations) {
			if (org.getName().equals(name))
				return;
		}
		organizations.add(new Organization(name));
		if(debug)System.out.println("Org: " + name);
	}

	/**
	 * Get the global organization list.
	 * 
	 * @return organizations
	 */
	public ArrayList<Organization> getOrganizations() {
		return organizations;
	}

	/**
	 * Add a single place
	 * 
	 * @param name
	 * @param isCapital
	 */
	public void addPlace(String name) {
		places.add(new Place(name));
	}

	/**
	 * New place from cities.xml parsing
	 * 
	 * @param place
	 * @param inCountry
	 * @param isCapital
	 */
	public void addPlace(Place place, String inCountry, boolean isCapital) {
		for (Country c : countries) {
			if (c.getShortName().equals(inCountry)) {
				boolean replaced = false; // check if place exists already
				for (Place p : places) {
					if (p.getName().equals(place.getName())) {
						p.setLatitude(place.getLatitude());
						p.setLongitude(place.getLongitude());
						p.setInhabitants(place.getInhabitants());
						p.setCountry(c);
						replaced = true;
						break;
					}
				}
				if (!replaced) { // else add new place
					places.add(new Place(place.getName(), place.getLatitude(),
							place.getLongitude(), place.getInhabitants(), c));
					if (isCapital) {
						c.setCapital(places.get(places.size() - 1));
					}
				}
			}
		}
	}

	public ArrayList<Place> getPlaces() {
		return places;
	}

	/**
	 * Replace a duplicate country and check if the capital has an attached
	 * country.
	 * 
	 * @param dublicate
	 * @param countryToAdd
	 */
	public void replaceCountry(int dublicate, Country countryToAdd) {
		countries.set(dublicate, countryToAdd);

		// check if added country has a capital + add country to this place
		if (countryToAdd.getCapital() != null) {
			for (Place p : places) {
				if (p.getName().equals(countryToAdd.getCapital().getName())) {
					p.setCountry(countries.get(dublicate));
				}
			}
		}
	}

	/**
	 * Check if country is duplicate or not, return the position.
	 * 
	 * @param name
	 *            name of the country
	 * @return int duplicate position in the ArrayList, -1 if not duplicate
	 */
	public int duplicateCountryPosition(String name) {
		int duplicate = 0;
		for (Country countrySaved : countries) {
			if (countrySaved.getShortName().equals(name)) {
				return duplicate;
			}
			duplicate++;
		}
		return -1;
	}

	/**
	 * Add or replace the parsed data from a single country.
	 * 
	 * @param country
	 */
	public void replaceOrAddCountry(Country country) {
		int duplicate = duplicateCountryPosition(country.getShortName());

		if (duplicate != -1) {
			replaceCountry(duplicate, country);
		} else {
			addCountry(country);
			// TODO uncomment
//			countries.get(countries.size() - 1).getCapital()
//					.setCountry(countries.get(countries.size() - 1));
		}
	}

	/**
	 * Add a year data to the specified country.
	 * 
	 * @param year
	 *            Year
	 * @param countryToAdd
	 *            Country
	 */
	public void addYearDataToCountry(Year year, Country countryToAdd) {
		for (Country country : countries) {
			if (country.getShortName().equals(countryToAdd.getShortName())) {
				country.addYear(year);
			}
		}
	}

	/**
	 * Return an existent country or create new one.
	 * 
	 * @param name
	 *            String
	 * @return Country
	 */
	public Country getCountry(String name) {
		for (Country country : countries) {
			if (country.getShortName().equals(name)) {
				return country;
			}
		}
		return new Country(name);
	}

	/**
	 * Add or replace a place and set the capital of the country to this place.
	 * Replacing needed if capital changed.
	 * 
	 * @param capital
	 *            String
	 * @param country
	 *            Country
	 * @return Country with the capital set up
	 */
	public Country getCountryWithCapital(String capital, Country country) {
		int count = 0;
		boolean replace = false;
		for (Place p : places) {
			if (p.getName().equals(capital)) {
				places.set(count, new Place(capital));
				country.setCapital(places.get(count));
				replace = true;
				break;
			}
			count++;
		}
		if (!replace) {
			addPlace(capital); // TODO City without Country
			country.setCapital(places.get(places.size() - 1));
		}
		return country;
	}

	public void addPort(String port, String country) {
		int count = 0;
		for (Place p : places) {
			if (p.getName().equals(port) && p.getCountry().getShortName().equals(country)) {
				if(debug)System.out.println("if in addPort");
				places.get(count).setPort(true);
				return;
			}
			count++;
		}
		// TODO what if port is not found?
	}
}